/*
package thread;

import java.util.Comparator;
import java.util.PriorityQueue;

*/
/*
*
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-09-26
 * Time: 9:36

*//*


//1：首先创建一个定时器类
class MyTimer{
    //2：需要一个线程来扫描队列（只需要指向队列中的队首元素）
    private Thread t = null;
    //3:创建一个优先级队列,思考创建完了，就得放任务进去
    //10:把任务作为泛型放进队列
    private PriorityQueue<MyTimerTask> queue = new PriorityQueue();
    //23:这里main方法中添加任务和MyTimer中出任务会引发多线程安全问题，这里我们使用锁对象来保护队列,那么在哪里加锁比较合适呢
    Object locker = new Object();
    //13：需要去写一个方法，把参数传入
    public void schedule(Runnable runnable , long delay){
        //24.5:参与到锁竞争中的schedule也需要加上锁，因为涉及到队列offer操作
        synchronized(locker){
            //14:通过MyTimerTask构造
            MyTimerTask task = new MyTimerTask(runnable , delay);
            //15:再把任务放到队列里面
            queue.offer(task);
            //26:offer后有元素了，唤醒
            locker.notify();
        }

    }

    //16:通过构造方法，让t线程扫描判断队首任务是否到达时间
    public MyTimer(){
        t = new Thread(()->{
    //17：t线程去扫描队首元素，如果时间到就删除队首元素，并执行任务，如果没到就等待
            while(true){
    //24:加锁，得加到while循环里面来，如果加到外面，当我们在main方法中newMyTimer的时候
    //就会调用构造方法加锁，然后一直while循环出不来，解不了锁，进而参与锁竞争中的schedule就解不了锁
                try{
                    synchronized(locker){
                        //17.5:如果队列为空等待
                        //27:While和notify捆绑使用，所以把if修改为while保险点，不懂的看阿华写的前面的文章哈
                        while (queue.isEmpty()){
                            //25：队列为空wait,catch异常，我们把try放到最外面
                            locker.wait();
                        }
                        //18:peek一下，获取队首元素
                        MyTimerTask task = queue.peek();
                        //19：记录下当前绝对时间
                        long curTime = System.currentTimeMillis();
                        //20:比较当前绝对时间和任务要执行的绝对时间大小
                        if(curTime >= task.getTime()){
                            //21:若大于等于，则出队列执行
                            queue.poll();
                            task.run();//此处顺序无所谓
                        }else {
                            //22:未到时间则等待
                               */
/* continue;*//*


                            //28:省下资源
                            locker.wait(task.getTime() - System.currentTimeMillis());
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }

            }
        });
        t.start();
    }




}

//4：通过MyTimerTask这个类来描述一个任务
class MyTimerTask implements Comparable<MyTimerTask>{
    //5：任务执行时间（绝对时间，ms级别的时间戳）
    private long time;
    //6:具体要执行的任务(runnable)
    private Runnable runnable;
    //20:获取一下任务执行的绝对时间
    public long getTime(){
        return time;
    }
    //7:写构造方法对成员变量初始化
    public MyTimerTask(Runnable runnable , long delay){
    //8:time(绝对时间 = 当前时间 + 设置的倒计时)
        this.time = System.currentTimeMillis() + delay ;
        this.runnable = runnable;

    }
    //9：通过一个方法来执行任务（调用runnable中的run方法）
    public void run(){
        runnable.run();
    }

    //11:实现接口，写比较器（导java.lang这个包）
    @Override
    public int compareTo(MyTimerTask o) {
        //12:返回时间小的那个任务（多试试）——至此为第一部分
        return (int)(this.time - o.time);
    }
}
public class ThreadDemon33 {
    public static void main(String[] args) {
        MyTimer timer = new MyTimer();
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("第三次测试,等待的相对时间为三秒");
            }
        },3000);
        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("第一次测试,等待的相对时间为一秒");
            }
        },1000);

        timer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("第二次测试,等待的相对时间为二秒");
            }
        },2000);
        System.out.println("hello main");
    }
}
*/
